home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
MATHS
/
MOONTOOL
/
!MoonTool
/
!Help
next >
Wrap
Text File
|
1993-08-09
|
35KB
|
1,123 lines
/*
Moon Tool for the Archimedes
============================
Sun Workstation version ................ John Walker
Archimedes Risc OS 3.1 port ............ Edouard Poor
This program is in the public domain:
"Do what thou wilt shall be the whole of the law".
Introduction
============
MoonTool is a program designed give you the following infomation:
o Phase of the Moon
o Age of the Moon
o Distance to the moon
o Dates of the Last and Next New moon as well as the First and
Last Quarters and the Full Moon.
o Angle the Moon subtends
In addition it also gives you information about:
o Time and Date in Julian, Local and Universal (GMT) times.
o Distance to the Sun
o Angle the Sun subtends
An invaluable tool for those of you who don't like going outside to look
at the moon, all the nethack players among you, astronomers who like
to know when the moon it new and thus the stars are at their best viewing,
or indeed anyone who just really needs to exactly how far away the moon
and sun are...
Interface
=========
The program starts up in it's iconised mode, giving you a simple window
with a single button displaying a picture of the moon as it appears
in the sky. You can move the window with its title bar, or click on the
icon to bring up the full, un-iconised, view.
In un-iconised mode you are presented with all the information about the
current time, the moons distance and age, the suns distance, and the
"Moon Phase" icon. Looking to the top right of the window you will see
that it has a full-size icon; clicking on this will reveal additional
information about the dates of the phases of the moon (all in UTC, or
Universal Time).
Clicking again on the "Moon Phase" icon of the moons current appearance
will put the program back into iconised mode.
Quitting the prgram simply consists of closing the window when it is
in un-iconised mode.
Risc OS 3.1 Notes
=================
This program needs both Local Time and Greenwich Mean Time set up
correctly in your machine.
This requires two things-- Firstly setting the configured time in your
machine to Greenwich Mean Time then getting the time correct for
where you live by setting the Congfiguration Setting 'TimeZone' (you
can type "help TimeZone" on the command line). This step will probably
be unnessesary in the UK where you are on GMT anyway...
Where I live (in New Zealand) I use "configure TimeZone +12:0"
The second step is to do with daylight savings-- Use !Alarm to toggle
between daylight savings on and off instead of altering the time or
the TimeZone offset. (Daylight Savings Time or DST is labeled 'BST'
in !Alarms 'Set Time' window, which stands for British Summer Time,
because Acorn is Very Good at Internationalisation...)
If you set and maintain the time in the method outlined above, you
will always be able to have the correct time, and be able to work
out the time in GMT or UTC as well, as will any program that needs
to know the time in both local and universal. C programs that use
localtime() and gmtime(), for example, need this.
Problems
========
There are no problems or bugs with this program. It is perfect in every
way and any difficulties you may experience are one of the three following
people, or organisation's fault:
o Yourself
o Your Acorn Dealer
o Acorn Computers Limited
For example you might say "When I run !MoonTool on my RO2 machine it
crashes" - This would be your fault for not purchasing Risc OS 3.1 yet.
You might say "In 256 colour mode the button plinths in, but it also
inverts as well" - This would be Acorns fault for not having better
'Kwality Kontrol' on its operating systems.
Also someone might complain "When the moon behind a cloud I can't see it
but I can still it on my computer. Could you set it up so that it's
visiability is always the same as the real moon?" - This would be their
dealers fault for selling a computer to someone whose IQ was obviously
in the low 70's...
In short, if you havn't worked it out yet, I take no responibility for
anything at all to do with this program.
To Be Done
==========
Well everything is actually about as well done as it's likely to get,
but if anyone wants to send me any improvments to the address below
I'd be very grateful, and will release anothr version with your
modifications and credit.
Also if anyone can design me a better Filer Icon I'd be most happy
to replace the one I've got at the moment...
If anyone feels like spell checking this !Help file I'm sure hundreds,
if not thousands, of english speakers around the world would be grateful
to you :-)
Author Info (Archimedes Version)
================================
Send all snail mail/money orders/cheques/cash to:
Edouard Poor
15 Stanley Pt Rd
Devonport
Auckland
New Zealand
Email/uu-files may be addressed to:
epoo1@cs.aukuni.ac.nz (valid until at least March 1994)
edouard@nacjack.gen.nz (not used very often)
Voice line:
+64 9 4450330
Bibliography
============
The algorithms used in this program to calculate the positions Sun and
Moon as seen from the Earth are given in the book "Practical Astronomy
With Your Calculator" by Peter Duffett-Smith, Second Edition, Cambridge
University Press, 1981. Ignore the word "Calculator" in the title; this
is an essential reference if you're interested in developing software
which calculates planetary positions, orbits, eclipses, and the like. If
you're interested in pursuing such programming, you should also obtain:
"Astronomical Formulae for Calculators" by Jean Meeus, Third Edition,
Willmann-Bell, 1985. A must-have.
"Planetary Programs and Tables from -4000 to +2800" by Pierre Bretagnon
and Jean-Louis Simon, Willmann-Bell, 1986. If you want the utmost
(outside of JPL) accuracy for the planets, it's here.
"Celestial BASIC" by Eric Burgess, Revised Edition, Sybex, 1985. Very
cookbook oriented, and many of the algorithms are hard to dig out of the
turgid BASIC code, but you'll probably want it anyway.
Many of these references can be obtained from Willmann-Bell, P.O. Box
35025, Richmond, VA 23235, USA. Phone: (804) 320-7016. In addition to
their own publications, they stock most of the standard references for
mathematical and positional astronomy.
Sun Workstation (Original) Author Info
======================================
A Moon for the Sun
Release 2.0
Designed and implemented by John Walker in December 1987,
revised and updated in February of 1988.
This program was written by:
John Walker
Autodesk, Inc.
2320 Marinship Way
Sausalito, CA 94965
(415) 332-2344 Ext. 829
Usenet: {sun!well}!acad!kelvin
I'd appreciate receiving any bug fixes and/or enhancements, which I'll
incorporate in future versions of the program. Please leave the original
attribution information intact so that credit and blame may be properly
apportioned.
Source Code
===========
Well it was originally compiled with my own personal library "QDD_Lib"
but it uses very few calls, and they are all, unlike Acorns "RISC_OSLib"
ones, very easy to read. It should be very easy for anyone with a C
compiler and any set of wimp libraries to convert this program to
compile under their own set-up.
Enjoy.
*
*
*
* Astronomical constants
*/
#define epoch 2444238.5 /* 1980 January 0.0 */
/*
* Constants defining the Sun's apparent orbit
*/
#define elonge 278.833540 /* Ecliptic longitude of the Sun at epoch 1980.0 */
#define elongp 282.596403 /* Ecliptic longitude of the Sun at perigee */
#define eccent 0.016718 /* Eccentricity of Earth's orbit */
#define sunsmax 1.495985e8 /* Semi-major axis of Earth's orbit, km */
#define sunangsiz 0.533128 /* Sun's angular size, degs, at semi-major axis distance */
/*
* Elements of the Moon's orbit, epoch 1980.0
*/
#define mmlong 64.975464 /* Moon's mean lonigitude at the epoch */
#define mmlongp 349.383063 /* Mean longitude of the perigee at the epoch */
#define mlnode 151.950429 /* Mean longitude of the node at the epoch */
#define minc 5.145396 /* Inclination of the Moon's orbit */
#define mecc 0.054900 /* Eccentricity of the Moon's orbit */
#define mangsiz 0.5181 /* Moon's angular size at distance a from Earth */
#define msmax 384401.0 /* Semi-major axis of Moon's orbit in km */
#define mparallax 0.9507 /* Parallax at distance a from Earth */
#define synmonth 29.53058868 /* Synodic month (new Moon to new Moon) */
#define lunatbase 2423436.0 /* Base date for E. W. Brown's numbered series
of lunations (1923 January 16) */
/*
* Properties of the Earth
*/
#define earthrad 6378.16 /* Radius of Earth in kilometres */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
/*
* Handy mathematical functions and constants
*/
#define EPSILON 1E-6
#define PI 3.14159265358979323846 /* Assume not near black hole nor in Tennessee */
#define sgn(x) (((x) < 0) ? -1 : ((x) > 0 ? 1 : 0)) /* Extract sign */
#define abs(x) ((x) < 0 ? (-(x)) : (x)) /* Absolute val */
#define fixangle(a) ((a) - 360.0 * (floor((a) / 360.0))) /* Fix angle */
#define torad(d) ((d) * (PI / 180.0)) /* Deg->Rad */
#define todeg(d) ((d) * (180.0 / PI)) /* Rad->Deg */
#define dsin(x) (sin(torad((x)))) /* Sin from deg */
#define dcos(x) (cos(torad((x)))) /* Cos from deg */
#define FALSE 0
#define TRUE 1
static int testmode = FALSE; /* Rapid warp through time for debugging */
static int Iconised = TRUE;
/* Forward functions */
double jtime(struct tm *);
double phase(double, double *, double *, double *, double *, double *, double *);
void phasehunt(double, double *);
void ringgg(void);
void drawmoon(double);
void jyear(double, int *, int *, int *);
void jhms(double, int *, int *, int *);
#define Plural(x) (x) == 1 ? "" : "s"
/***********************************************/
#include "Wimp.h"
#include "GFX.h"
#define Julian_Date 4
#define Local_Time 7
#define Local_Date 8
#define Universal_Time 11
#define Universal_Date 12
#define Moon_Subtends 17
#define MoonDistance_Kilometers 20
#define MoonDistance_Radii 21
#define MoonAge_Days 27
#define MoonAge_Hours 28
#define MoonAge_Minutes 29
#define Sun_Subtends 34
#define SunDistance_Kilometers 37
#define SunDistance_AU 38
#define Phases_LastNewMoon 45
#define Phases_FirstQuarter 48
#define Phases_FullMoon 51
#define Phases_LastQuarter 54
#define Phases_NextNewMoon 57
#define Phases_CurrentLunation 61
taskhandle OurTaskHandle;
windowhandle MoonTool;
windowhandle MoonIcon;
char temp[128]; /* A temporary string buffer */
/*
* Useful Risc OS functions
*/
void Icon_SmartPrint(iconhandle i, char *format, ...)
{
va_list argp;
iconstate info;
char *source;
char *dest;
int length;
va_start(argp, format);
vsprintf(temp, format, argp);
va_end(argp);
Wimp_GetIconState(MoonTool, i, &info);
if(info.icon.flags.feild.indirected)
{
dest = info.icon.data.indirectedtext.buffer;
length = info.icon.data.indirectedtext.bufflen-1;
}
else
{
dest = info.icon.data.text;
length = 11;
}
source = temp;
if(strncmp(dest, source, length) != 0)
{
strncpy(dest, source, length);
Wimp_SetIconState(MoonTool, i, 0, 0);
}
}
void StartWimp(void)
{
int i;
int isize;
int windowsize;
BOOL fontspresent;
window *moontoolwindow;
window *mooniconwindow;
window *scratchwindow;
void *moontoolispace;
void *mooniconispace;
windowstate wstate;
templatefonts fonts;
/*
** Initialise my I/O variables ...
*/
Wimp_Initialise200("Moon Tool", &OurTaskHandle);
Wimp_OpenTemplate("MoonTool:Templates");
Wimp_NamedTemplateSize("MoonTool", &isize, &windowsize, &fontspresent);
for(i=0; i<256; i++)
fonts.font[i] = 0;
scratchwindow = (window *) malloc(windowsize+isize);
moontoolispace = (void *) malloc(isize);
Wimp_LoadNamedTemplate(scratchwindow, "MoonTool", moontoolispace, isize, &fonts);
Wimp_CreateWindow(scratchwindow, &MoonTool);
Wimp_NamedTemplateSize("MoonIcon", &isize, &windowsize, &fontspresent);
scratchwindow = (window *) realloc(scratchwindow, windowsize+isize);
mooniconispace = (void *) malloc(isize);
Wimp_LoadNamedTemplate(scratchwindow, "MoonIcon", mooniconispace, isize, NULL);
Wimp_CreateWindow(scratchwindow, &MoonIcon);
Wimp_CloseTemplate();
if(Iconised)
wstate.handle = MoonIcon;
else
wstate.handle = MoonTool;
Wimp_GetWindowState(&wstate);
Wimp_OpenWindow((openwindowinfo *) &wstate);
free(scratchwindow);
}
/*
* Dispatch Poll
*/
void DispatchPoll(eventinfo *event)
{
switch (event->type)
{
case Open_Window_Request :
Wimp_OpenWindow(&event->data.window);
break;
case Close_Window_Request :
Wimp_CloseDown();
exit(0);
break;
case Mouse_Button_Change:
{
windowstate state;
if(event->data.buttonchange.pointerinfo.buttons.feild.menu)
/*MakeMenu(event)*/;
else
{
eventinfo dummyevent;
if(event->data.buttonchange.pointerinfo.window == MoonTool &&
event->data.buttonchange.pointerinfo.icon == 42)
{
Wimp_CloseWindow(MoonTool);
Wimp_PollIdleSeconds(&dummyevent, 0, 0);
DispatchPoll(&dummyevent);
state.handle = MoonIcon;
Wimp_GetWindowState(&state);
state.behind = OPEN_ON_TOP;
Wimp_OpenWindow((openwindowinfo *) &state);
Iconised = TRUE;
}
if(event->data.buttonchange.pointerinfo.window == MoonIcon)
{
Wimp_CloseWindow(MoonIcon);
Wimp_PollIdleSeconds(&dummyevent, 0, 0);
DispatchPoll(&dummyevent);
Iconised = FALSE; /* Have to set this before we call ringgg(); */
ringgg();
state.handle = MoonTool;
Wimp_GetWindowState(&state);
state.behind = OPEN_ON_TOP;
Wimp_OpenWindow((openwindowinfo *) &state);
}
}
}
break;
case Menu_Select:
{
if(event->data.menu[0] == 1) exit(0);
}
break;
case Key_Pressed:
Wimp_ProcessKey(event->data.key.code);
break;
case Send_Message:
case Send_Message_Acknowledged:
switch(event->data.message.header.type)
{
case Message_CloseDown:
Wimp_CloseDown();
exit(1);
break;
}
break;
}
}
/* Main program */
int main(int argc, char *argv[])
{
int i;
int delay;
eventmask mask = 0;
eventinfo event;
for (i = 1; i < argc; i++)
{
if (*argv[i] == '-' && argv[i][1] == 't')
testmode = TRUE;
}
StartWimp();
ringgg();
while(TRUE)
{
if(Iconised && !testmode)
delay = 6000;
else
delay = 90;
Wimp_PollIdleSeconds(&event, mask, delay);
if(event.type == Null_Reason_Code)
ringgg();
else
DispatchPoll(&event);
}
}
/*
* DRAWMOON -- Construct icon for moon, given phase of moon.
*/
int IconSpanlist[36][2];
#define Left 0
#define Right 1
#define XMid 35
void drawmoon(double ph)
{
int i, j, lx, rx;
double cp, xscale, d;
BOOL IconChanged = FALSE;
spritecontext SavedContext;
xscale = cos(2 * PI * ph);
for (i = 0; i < 29; i++)
{
d = (i*2.0+1.0) / 29.0;
if(d <= 1.0)
d = 1.0 - d;
else
d = d - 1.0;
cp = 31.0 * cos(asin(d));
if (ph < 0.5)
{
rx = 1000;
lx = XMid - xscale * cp;
}
else
{
lx = 0;
rx = XMid + xscale * cp;
}
if((IconSpanlist[i][Left] != lx) || (IconSpanlist[i][Right] != rx))
{
IconSpanlist[i][Left] = lx;
IconSpanlist[i][Right] = rx;
IconChanged = TRUE;
}
}
/*
* Only update icon if it changed (this eliminates gratuitous
* flashing of the icon on-screen).
*/
if(IconChanged)
{
GFX_ChangeContextToSpriteMask(1, "the_moon", &SavedContext);
GFX_GCOL(15); /* No Mask */
GFX_Rectangle(0,0,1000,1000); /* Clear whole sprite */
GFX_GCOL(0); /* Mask */
for(i=0; i<29; i++)
{
GFX_Line(IconSpanlist[i][Left]*2, i*4 + 8, IconSpanlist[i][Right]*2, i*4 + 8);
}
GFX_RestoreContext(&SavedContext);
Wimp_SetIconState(MoonTool, 41, 0, 0);
Wimp_SetIconState(MoonIcon, 0, 0, 0);
}
}
/* RINGGG -- Update status on interval timer ticks and redraw
window if needed. */
void ringgg(void)
{
int lunation, wclosed;
time_t t;
double jd, p, aom, cphase, cdist, cangdia, csund, csuang, lptime;
static double phasar[5];
static double nptime = 0.0; /* Next new moon time */
static int updyet = 0; /* Update interval when window closed */
static int firstime = TRUE; /* Calculate text page first time */
char amsg[12], tbuf[80];
static double faketime = 0.0;
static short moonilast[64][4] = {0};
int yy, mm, dd, hh, mmm, ss;
struct tm *gm;
static char *moname[] = {"January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December"};
(void) time(&t);
jd = jtime((gm = gmtime(&t)));
if(testmode)
{
if (faketime == 0.0)
faketime = jd + 1;
else
faketime += 1.0 / 24;
jd = faketime;
}
p = phase(jd, &cphase, &aom, &cdist, &cangdia, &csund, &csuang);
/*
* Calculate times of phases of this lunation.
* This is sufficiently time-consuming that
* we only do it once a month.
*/
if(jd > nptime)
{
phasehunt(jd, phasar); /* X-pensive call */
}
drawmoon(p);
/* If we're iconic, there's nothing more to do. */
if (Iconised && !firstime)
return;
/*
* Update textual information for open window
*/
firstime = FALSE;
Icon_SmartPrint(Julian_Date, "%.5f", jd + 0.5);
if(testmode)
{
jyear(jd, &yy, &mm, &dd);
jhms(jd, &hh, &mmm, &ss);
Icon_SmartPrint(Universal_Time, "%02d:%02d:%02d", hh, mmm, ss);
Icon_SmartPrint(Universal_Date, "%d %s %d", dd, moname[mm-1], yy);
}
else
{
Icon_SmartPrint(Universal_Time, "%02d:%02d:%02d", gm->tm_hour, gm->tm_min, gm->tm_sec);
Icon_SmartPrint(Universal_Date, "%d %s %d", gm->tm_mday, moname[gm->tm_mon], gm->tm_year + 1900);
}
gm = localtime(&t);
if(testmode)
{
Icon_SmartPrint(Local_Time, "--:--:--");
Icon_SmartPrint(Local_Date, "(Test Mode)");
}
else
{
Icon_SmartPrint(Local_Time, "%02d:%02d:%02d", gm->tm_hour, gm->tm_min, gm->tm_sec);
Icon_SmartPrint(Local_Date, "%d %s %d", gm->tm_mday, moname[gm->tm_mon], gm->tm_year + 1900);
}
/*
* sprintf(tbuf, "Moon phase: %d%% 0%% = New, 100%% = Full ",
* (int) (cphase * 100));
* prt(5);
*/
/*
* Information about the Moon
*/
Icon_SmartPrint(Moon_Subtends, "%.4f°", cangdia);
Icon_SmartPrint(MoonDistance_Kilometers, "%ld kilometres", (long) cdist);
Icon_SmartPrint(MoonDistance_Radii, "%.1f Earth radii", cdist / earthrad);
aom = jd - phasar[0]; /* Cos it was wrong -- Edouard Poor */
Icon_SmartPrint(MoonAge_Days, "%d", (int) aom);
Icon_SmartPrint(MoonAge_Hours, "%d", ((int) (24 * (aom - floor(aom)))));
Icon_SmartPrint(MoonAge_Minutes, "%d", ((int) (1440 * (aom - floor(aom)))) % 60);
/*
* Edit information about the Sun
*/
Icon_SmartPrint(Sun_Subtends, "%.4f°", csuang);
Icon_SmartPrint(SunDistance_Kilometers, "%.0f kilometres", csund);
Icon_SmartPrint(SunDistance_AU, "%.3f A.U.", csund / sunsmax);
/*
* Calculate times of phases of this lunation.
* This is sufficiently time-consuming that
* we only do it once a month.
*/
if(jd > nptime)
{
lptime = phasar[0];
jyear(lptime, &yy, &mm, &dd);
jhms(lptime, &hh, &mmm, &ss);
Icon_SmartPrint(Phases_LastNewMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
lptime = phasar[1];
jyear(lptime, &yy, &mm, &dd);
jhms(lptime, &hh, &mmm, &ss);
Icon_SmartPrint(Phases_FirstQuarter, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
lptime = phasar[2];
jyear(lptime, &yy, &mm, &dd);
jhms(lptime, &hh, &mmm, &ss);
Icon_SmartPrint(Phases_FullMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
lptime = phasar[3];
jyear(lptime, &yy, &mm, &dd);
jhms(lptime, &hh, &mmm, &ss);
Icon_SmartPrint(Phases_LastQuarter, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
nptime = phasar[4];
jyear(nptime, &yy, &mm, &dd);
jhms(nptime, &hh, &mmm, &ss);
Icon_SmartPrint(Phases_NextNewMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
lunation = floor(((lptime + 7) - lunatbase) / synmonth) + 1;
Icon_SmartPrint(Phases_CurrentLunation, "%d", lunation);
}
}
/* JDATE -- Convert internal GMT date and time to Julian day
and fraction. */
long jdate(struct tm *t)
{
long c, m, y;
y = t->tm_year + 1900;
m = t->tm_mon + 1;
if (m > 2)
m = m - 3;
else
{
m = m + 9;
y = y - 1;
}
c = y / 100L; /* Compute century */
y -= 100L * c;
return t->tm_mday + (c * 146097L) / 4 + (y * 1461L) / 4 +
(m * 153L + 2) / 5 + 1721119L;
}
/* JTIME -- Convert internal GMT date and time to astronomical Julian
time (i.e. Julian date plus day fraction, expressed as
a double). */
double jtime(struct tm *t)
{
return (jdate(t) - 0.5) +
(t->tm_sec + 60 * (t->tm_min + 60 * t->tm_hour)) / 86400.0;
}
/* JYEAR -- Convert Julian date to year, month, day, which are
returned via integer pointers to integers. */
void jyear(double td, int *yy, int *mm, int *dd)
{
double j, d, y, m;
td += 0.5; /* Astronomical to civil */
j = floor(td);
j = j - 1721119.0;
y = floor(((4 * j) - 1) / 146097.0);
j = (j * 4.0) - (1.0 + (146097.0 * y));
d = floor(j / 4.0);
j = floor(((4.0 * d) + 3.0) / 1461.0);
d = ((4.0 * d) + 3.0) - (1461.0 * j);
d = floor((d + 4.0) / 4.0);
m = floor(((5.0 * d) - 3) / 153.0);
d = (5.0 * d) - (3.0 + (153.0 * m));
d = floor((d + 5.0) / 5.0);
y = (100.0 * y) + j;
if (m < 10.0)
m = m + 3;
else
{
m = m - 9;
y = y + 1;
}
*yy = y;
*mm = m;
*dd = d;
}
/* JHMS -- Convert Julian time to hour, minutes, and seconds. */
void jhms(double j, int *h, int *m, int *s)
{
long ij;
j += 0.5; /* Astronomical to civil */
ij = (j - floor(j)) * 86400.0;
*h = ij / 3600L;
*m = (ij / 60L) % 60L;
*s = ij % 60L;
}
/* MEANPHASE -- Calculates mean phase of the Moon for a given
base date and desired phase:
0.0 New Moon
0.25 First quarter
0.5 Full moon
0.75 Last quarter
Beware!!! This routine returns meaningless
results for any other phase arguments. Don't
attempt to generalise it without understanding
that the motion of the moon is far more complicated
that this calculation reveals. */
double meanphase(double sdate, double phase, double *usek)
{
int yy, mm, dd;
double k, t, t2, t3, nt1;
jyear(sdate, &yy, &mm, &dd);
k = (yy + ((mm - 1) * (1.0 / 12.0)) - 1900) * 12.3685;
/* Time in Julian centuries from 1900 January 0.5 */
t = (sdate - 2415020.0) / 36525;
t2 = t * t; /* Square for frequent use */
t3 = t2 * t; /* Cube for frequent use */
*usek = k = floor(k) + phase;
nt1 = 2415020.75933 + synmonth * k
+ 0.0001178 * t2
- 0.000000155 * t3
+ 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
return nt1;
}
/* TRUEPHASE -- Given a K value used to determine the
mean phase of the new moon, and a phase
selector (0.0, 0.25, 0.5, 0.75), obtain
the true, corrected phase time. */
double truephase(double k, double phase)
{
double t, t2, t3, pt, m, mprime, f;
int apcor = FALSE;
k += phase; /* Add phase to new moon time */
t = k / 1236.85; /* Time in Julian centuries from
1900 January 0.5 */
t2 = t * t; /* Square for frequent use */
t3 = t2 * t; /* Cube for frequent use */
pt = 2415020.75933 /* Mean time of phase */
+ synmonth * k
+ 0.0001178 * t2
- 0.000000155 * t3
+ 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
m = 359.2242 /* Sun's mean anomaly */
+ 29.10535608 * k
- 0.0000333 * t2
- 0.00000347 * t3;
mprime = 306.0253 /* Moon's mean anomaly */
+ 385.81691806 * k
+ 0.0107306 * t2
+ 0.00001236 * t3;
f = 21.2964 /* Moon's argument of latitude */
+ 390.67050646 * k
- 0.0016528 * t2
- 0.00000239 * t3;
if ((phase < 0.01) || (abs(phase - 0.5) < 0.01))
{
/* Corrections for New and Full Moon */
pt += (0.1734 - 0.000393 * t) * dsin(m)
+ 0.0021 * dsin(2 * m)
- 0.4068 * dsin(mprime)
+ 0.0161 * dsin(2 * mprime)
- 0.0004 * dsin(3 * mprime)
+ 0.0104 * dsin(2 * f)
- 0.0051 * dsin(m + mprime)
- 0.0074 * dsin(m - mprime)
+ 0.0004 * dsin(2 * f + m)
- 0.0004 * dsin(2 * f - m)
- 0.0006 * dsin(2 * f + mprime)
+ 0.0010 * dsin(2 * f - mprime)
+ 0.0005 * dsin(m + 2 * mprime);
apcor = TRUE;
}
else if ((abs(phase - 0.25) < 0.01 || (abs(phase - 0.75) < 0.01)))
{
pt += (0.1721 - 0.0004 * t) * dsin(m)
+ 0.0021 * dsin(2 * m)
- 0.6280 * dsin(mprime)
+ 0.0089 * dsin(2 * mprime)
- 0.0004 * dsin(3 * mprime)
+ 0.0079 * dsin(2 * f)
- 0.0119 * dsin(m + mprime)
- 0.0047 * dsin(m - mprime)
+ 0.0003 * dsin(2 * f + m)
- 0.0004 * dsin(2 * f - m)
- 0.0006 * dsin(2 * f + mprime)
+ 0.0021 * dsin(2 * f - mprime)
+ 0.0003 * dsin(m + 2 * mprime)
+ 0.0004 * dsin(m - 2 * mprime)
- 0.0003 * dsin(2 * m + mprime);
if(phase < 0.5)
/* First quarter correction */
pt += 0.0028 - 0.0004 * dcos(m) + 0.0003 * dcos(mprime);
else
/* Last quarter correction */
pt += -0.0028 + 0.0004 * dcos(m) - 0.0003 * dcos(mprime);
apcor = TRUE;
}
if(!apcor)
{
fprintf(stderr, "TRUEPHASE called with invalid phase selector.\n");
exit(1);
}
return pt;
}
/* PHASEHUNT -- Find time of phases of the moon which surround
the current date. Five phases are found, starting
and ending with the new moons which bound the
current lunation. */
void phasehunt(double sdate, double phases[5])
{
double adate, k1, k2, nt1, nt2;
adate = sdate - 45;
nt1 = meanphase(adate, 0.0, &k1);
while (TRUE)
{
adate += synmonth;
nt2 = meanphase(adate, 0.0, &k2);
if (nt1 <= sdate && nt2 > sdate)
break;
nt1 = nt2;
k1 = k2;
}
phases[0] = truephase(k1, 0.0);
phases[1] = truephase(k1, 0.25);
phases[2] = truephase(k1, 0.5);
phases[3] = truephase(k1, 0.75);
phases[4] = truephase(k2, 0.0);
}
/* KEPLER -- Solve the equation of Kepler. */
double kepler(double m, double ecc)
{
double e, delta;
e = m = torad(m);
do
{
delta = e - ecc * sin(e) - m;
e -= delta / (1 - ecc * cos(e));
}
while (abs(delta) > EPSILON);
return e;
}
/* PHASE -- Calculate phase of moon as a fraction:
The argument is the time for which the phase is requested,
expressed as a Julian date and fraction. Returns the terminator
phase angle as a percentage of a full circle (i.e., 0 to 1),
and stores into pointer arguments the illuminated fraction of
the Moon's disc, the Moon's age in days and fraction, the
distance of the Moon from the centre of the Earth, and the
angular diameter subtended by the Moon as seen by an observer
at the centre of the Earth.
pphase.............Illuminated fraction
mage...............Age of moon in days
dist...............Distance in kilometres
angdia.............Angular diameter in degrees
sudist.............Distance to Sun
suangdia...........Sun's angular diameter
*/
double phase(double pdate, double *pphase, double *mage, double *dist, double *angdia, double *sudist, double *suangdia)
{
double Day, N, M, Ec, Lambdasun, ml, MM, MN, Ev, Ae, A3, MmP,
mEc, A4, lP, V, lPP, NP, y, x, Lambdamoon, BetaM,
MoonAge, MoonPhase,
MoonDist, MoonDFrac, MoonAng, MoonPar,
F, SunDist, SunAng;
/* Calculation of the Sun's position */
Day = pdate - epoch; /* Date within epoch */
N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
M = fixangle(N + elonge - elongp); /* Convert from perigee co-ordinates to epoch 1980.0 */
Ec = kepler(M, eccent); /* Solve equation of Kepler */
Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
Ec = 2 * todeg(atan(Ec)); /* True anomaly */
Lambdasun = fixangle(Ec + elongp); /* Sun's geocentric ecliptic longitude */
F = ((1 + eccent * cos(torad(Ec))) / (1 - eccent * eccent)); /* Orbital distance factor */
SunDist = sunsmax / F; /* Distance to Sun in km */
SunAng = F * sunangsiz; /* Sun's angular size in degrees */
/*
* Calculation of the Moon's position
*/
/* Moon's mean longitude */
ml = fixangle(13.1763966 * Day + mmlong);
/* Moon's mean anomaly */
MM = fixangle(ml - 0.1114041 * Day - mmlongp);
/* Moon's ascending node mean longitude */
MN = fixangle(mlnode - 0.0529539 * Day);
/* Evection */
Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
/* Annual equation */
Ae = 0.1858 * sin(torad(M));
/* Correction term */
A3 = 0.37 * sin(torad(M));
/* Corrected anomaly */
MmP = MM + Ev - Ae - A3;
/* Correction for the equation of the centre */
mEc = 6.2886 * sin(torad(MmP));
/* Another correction term */
A4 = 0.214 * sin(torad(2 * MmP));
/* Corrected longitude */
lP = ml + Ev + mEc - Ae + A4;
/* Variation */
V = 0.6583 * sin(torad(2 * (lP - Lambdasun)));
/* True longitude */
lPP = lP + V;
/* Corrected longitude of the node */
NP = MN - 0.16 * sin(torad(M));
/* Y inclination coordinate */
y = sin(torad(lPP - NP)) * cos(torad(minc));
/* X inclination coordinate */
x = cos(torad(lPP - NP));
/* Ecliptic longitude */
Lambdamoon = todeg(atan2(y, x));
Lambdamoon += NP;
/* Ecliptic latitude */
BetaM = todeg(asin(sin(torad(lPP - NP)) * sin(torad(minc))));
/*
* Calculation of the phase of the Moon
*/
/* Age of the Moon in degrees */
MoonAge = lPP - Lambdasun;
/* Phase of the Moon */
MoonPhase = (1 - cos(torad(MoonAge))) / 2;
/*
* Calculate distance of moon from the centre of the Earth
*/
MoonDist = (msmax * (1 - mecc * mecc)) / (1 + mecc * cos(torad(MmP + mEc)));
/*
* Calculate Moon's angular diameter
*/
MoonDFrac = MoonDist / msmax;
MoonAng = mangsiz / MoonDFrac;
/*
* Calculate Moon's parallax
*/
MoonPar = mparallax / MoonDFrac;
*pphase = MoonPhase;
*mage = synmonth * (fixangle(MoonAge) / 360.0); /* ???? This can't be right ???? */
*dist = MoonDist;
*angdia = MoonAng;
*sudist = SunDist;
*suangdia = SunAng;
return fixangle(MoonAge) / 360.0;
}